<template>
    <div
        class="a-table"
        :class="[
            `color-${myColor}`,
            `size-${mySize}`,
            { sharp: mySharp },
            { disabled: myDisabled },
        ]"
    >
        <div class="header c-b">
            <table ref="headerTable">
                <tr>
                    <th
                        v-if="selectable"
                        @click="toggleSelectAll"
                        class="select-cell selectable"
                    >
                        <span
                            class="fa fa-fw fa-square-o"
                            v-show="!anySelected"
                        ></span>
                        <span
                            class="fa fa-fw fa-minus-square-o"
                            v-show="anySelected && !allSelected"
                        ></span>
                        <span
                            class="fa fa-fw fa-check-square-o"
                            v-show="allSelected && anySelected"
                        ></span>
                    </th>
                    <th
                        v-for="header in headerList"
                        :key="getHeaderNameFunc(header)"
                        :width="`${
                            (getHeaderWidthFunc(header) / headerTotalWidth) *
                            100
                        }%`"
                    >
                        <slot
                            :name="`header-${getHeaderNameFunc(header)}`"
                            :header="header"
                            >{{ getHeaderTextFunc(header) }}</slot
                        >
                    </th>
                </tr>
            </table>
        </div>
        <a-scrollable>
            <div
                v-show="dataList.length"
                class="data c-b-h c-b-b"
                :style="dataTableStyle"
            >
                <table ref="dataTable">
                    <tr
                        v-for="(data, dataIndex) in dataList"
                        :key="getKeyFunc(data)"
                        :class="[{ seleced: isItemSelected(data) }]"
                    >
                        <template v-if="selectable">
                            <td
                                v-if="getCanBeSelectedFunc(data)"
                                @click="toggleSelectItem(data)"
                                class="select-cell selectable"
                            >
                                <span
                                    v-if="isItemSelected(data)"
                                    class="fa fa-fw fa-check-square-o"
                                ></span>
                                <span
                                    v-else
                                    class="fa fa-fw fa-square-o"
                                ></span>
                            </td>
                            <td v-else class="select-cell"></td>
                        </template>
                        <td
                            v-for="(header, headerIndex) in headerList"
                            :key="getHeaderNameFunc(header)"
                            :width="`${
                                (getHeaderWidthFunc(header) /
                                    headerTotalWidth) *
                                100
                            }%`"
                        >
                            <slot
                                :name="`data-${getHeaderNameFunc(header)}`"
                                :header="header"
                                :headerIndex="headerIndex"
                                :data="data"
                                :dataIndex="dataIndex"
                                >{{ data[getHeaderNameFunc(header)] }}</slot
                            >
                        </td>
                    </tr>
                </table>
            </div>
        </a-scrollable>
        <slot name="emptyTips" v-if="!dataList.length">
            <div class="c-p-v-m c-w-100 c-align-center">没有任何数据</div>
        </slot>
    </div>
</template>

<style lang="scss" scoped>
@import "../scss/vars";

.a-table {
    width: 100%;
    table {
        width: 100%;
        border-collapse: collapse;
        table-layout: fixed;
    }

    .data tr {
        &:not(:last-child) {
            border-bottom: solid 1px $defaultBorderColor;
        }

        &.seleced {
            background-color: #eaeaea !important;
        }

        &:nth-child(even) {
            background-color: #fafafa;
        }
        &:hover {
            background-color: #f5f5f5;
        }
    }

    th,
    td {
        text-align: left;
        box-sizing: border-box;
        &:not(:last-child) {
            border-right: solid 1px $defaultBorderColor;
        }
    }
    @each $sizePackageName, $sizePackageValue in $sizePackages {
        &.size-#{$sizePackageName} {
            th,
            td {
                padding-left: map-get($sizePackageValue, "space");
                padding-right: map-get($sizePackageValue, "space");
                height: map-get($sizePackageValue, "size");
                font-size: map-get($sizePackageValue, "fontSize");
            }
        }
    }

    $defaultColorPackage: map-get(
        $map: $colorPackages,
        $key: "default",
    );

    $themeColor: map-get($defaultColorPackage, "themeColor");
    $frontColor: map-get($defaultColorPackage, "frontColor");
    $bgColor: map-get($defaultColorPackage, "bgColor");

    .select-cell {
        width: 60px;
        padding: 0;

        &.selectable {
            text-align: center;
            cursor: pointer;

            color: $themeColor;

            &:hover {
                color: $frontColor;
                background-color: lighten($bgColor, 10%);
            }
        }
    }
}
</style>

<script>
import AScrollable from './AScrollable.vue'
import inputMixin from "../common/inputMixin"

export default {
    components: { AScrollable },
    mixins: [inputMixin],
    props: {
        headerList: {
            type: Array,
            default: []
        },
        getHeaderNameFunc: {
            type: Function,
            default: a => a.name
        },
        getHeaderTextFunc: {
            type: Function,
            default: a => a.text
        },
        /**
         * 注意不是像素，而是权重
         */
        getHeaderWidthFunc: {
            type: Function,
            default: a => a.width
        },
        dataList: {
            type: Array,
            default: []
        },
        selectable: {
            type: Boolean,
            default: false,
        },
        value: {
            type: Array,
            default: []
        },
        getValueFunc: {
            type: Function,
            default: a => a.id
        },
        getKeyFunc: {
            type: Function,
            default: a => a.id
        },
        maxHeight: {
            type: Number,
            default: null
        },
        getCanBeSelectedFunc: {
            type: Function,
            default: a => true
        },
    },
    computed: {
        valueSet() {
            return new Set(this.value)
        },
        anySelected() {
            return this.dataList.some(a => this.valueSet.has(this.getValueFunc(a)))
        },
        allSelected() {
            return this.dataList.every(a => this.valueSet.has(this.getValueFunc(a)))
        },
        dataTableStyle() {
            if (this.maxHeight > 0) {
                return {
                    maxHeight: this.maxHeight + 'px',
                    overflowY: 'auto'
                }
            }
            return {}
        },
        headerTotalWidth() {
            let totalWidth = 0
            for (let a of this.headerList) {
                let headerWidth = this.getHeaderWidthFunc(a)
                totalWidth += headerWidth
            }
            return totalWidth
        },
    },
    methods: {
        input(val) {
            this.$emit('update:value', val)
        },
        toggleSelectItem(item) {
            let itemValue = this.getValueFunc(item)
            if (!this.isItemSelected(item)) {
                this.input([...this.value, itemValue])
            } else {
                this.input(this.value.filter(a => a != itemValue))
            }
        },
        isItemSelected(item) {
            let itemValue = this.getValueFunc(item)
            return this.valueSet.has(itemValue)
        },
        toggleSelectAll() {
            if (this.anySelected) {
                let dataListIdSet = new Set(this.dataList.map(a => this.getValueFunc(a)))
                this.input(this.value.filter(a => !dataListIdSet.has(a)))
            } else {
                let newIdList = this.value
                this.dataList.forEach(a => {
                    if (this.getCanBeSelectedFunc(a)) {
                        let id = this.getValueFunc(a)
                        if (!this.valueSet.has(id)) {
                            newIdList.push(id)
                        }
                    }
                })
                this.input(newIdList)
            }
        },
    },
}
</script>